/**
 * 
 */
package info.niwota.fwrite;

import info.niwota.commons.web.ContentHelper;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import android.content.Context;
import android.net.Uri;
import android.net.Uri.Builder;
import android.util.Log;

/**
 * @author qiangli
 *
 */
public class SessionManager {

	private static final String BIN_SEBD = "/content/info.niwota.fwrite/write/send";
	
	private static final String BIN_GET = "/content/info.niwota.fwrite/write/get";

	private static final String TAG = "SessionManager";

	private SessionManager() {
	}
	
	public static WriteActivity writer = null;
	
	public static SessionInfo[] listSession() {
		File[] msgs = SDCard.listSessions();
		int cnt = (msgs == null ? 0 : msgs.length);
		SessionInfo[] ss = new SessionInfo[cnt];
		for (int i = 0; i < cnt; i++) {
			ss[i] = new SessionInfo();
			ss[i].hasMessage = msgs[i].length() > 0;
			ss[i].peer = msgs[i].getName();
			ss[i].date = msgs[i].lastModified();
			ss[i].message = msgs[i].toURI();
		}
		return ss;
	}

	public static SessionInfo[] listIncomingMessages() {
		File[] msgs = SDCard.listMessages();
		int cnt = (msgs == null ? 0 : msgs.length);
		SessionInfo[] ss = new SessionInfo[cnt];
		for (int i = 0; i < cnt; i++) {
			ss[i] = new SessionInfo();
			ss[i].hasMessage = msgs[i].length() > 0;
			ss[i].peer = msgs[i].getName();
			ss[i].date = msgs[i].lastModified();
			ss[i].message = msgs[i].toURI();
		}
		return ss;
	}
	
	public static void ensureSession(String peer) {
		try {
			SDCard.ensureSession(peer);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void doneSession(String peer) {
		try {
			SDCard.removeSession(peer);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void sendKey(Context ctx, String peer, String key) throws Exception {
		Uri base = Uri.parse(BIN_SEBD);
		Builder b = base.buildUpon();
		b.appendQueryParameter("peer", peer);
		b.appendQueryParameter("cache", "false");
		b.appendQueryParameter("data", "false");
		b.appendQueryParameter("class", "key");
		b.appendQueryParameter("val", key);

		String path = b.toString();
		final Uri uri = ContentHelper.buildUri(path);

		String rs = ContentHelper.getContent(ctx, uri);
		checkStatus(ctx, rs);
	}
	
	public static void sendSmiley(Context ctx, String peer, int icon) throws Exception {
		Uri base = Uri.parse(BIN_SEBD);
		Builder b = base.buildUpon();
		b.appendQueryParameter("peer", peer);
		b.appendQueryParameter("cache", "false");
		b.appendQueryParameter("data", "false");
		b.appendQueryParameter("class", "smiley");
		b.appendQueryParameter("val", Smiley.map(icon));

		String path = b.toString();
		final Uri uri = ContentHelper.buildUri(path);

		String rs = ContentHelper.getContent(ctx, uri);
		checkStatus(ctx, rs);
	}
	
	public static void sendGuesture(Context ctx, String peer, GestureElement el, boolean autospace) throws Exception {
		Uri base = Uri.parse(BIN_SEBD);
		Builder b = base.buildUpon();
		b.appendQueryParameter("peer", peer);
		b.appendQueryParameter("cache", "false");
		b.appendQueryParameter("data", "false");
		
		b.appendQueryParameter("class", "gesture");
		b.appendQueryParameter("val", encode(el.toJSON().toString()));
		b.appendQueryParameter("autospace", Boolean.toString(autospace));
		
		String path = b.toString();
		final Uri uri = ContentHelper.buildUri(path);

		String rs = ContentHelper.getContent(ctx, uri);
		checkStatus(ctx, rs);
	}
	
	private static void checkStatus(Context ctx, String rs) throws Exception {
		if (Debug.DEBUG) {
			Log.d(TAG, rs);
		}
		if (rs.startsWith("STATUS-5") || rs.startsWith("STATUS-4")) {
			throw new Exception(rs);
		}	
	}

	private static String encode(String v) throws UnsupportedEncodingException {
		return URLEncoder.encode(v, "UTF-8");
	}

	public static void getFile(Context ctx, String peer, String  uri, File file) throws Exception {
		Uri base = Uri.parse(BIN_GET);
		Builder b = base.buildUpon();
		b.appendQueryParameter("peer", peer);
		b.appendQueryParameter("cache", "false");
		b.appendQueryParameter("data", "false");
		b.appendQueryParameter("uri", uri);

		String path = b.toString();
		final Uri u = ContentHelper.buildUri(path);
	
		ContentHelper.saveContent(ctx, u, file);
	}

	
	private static int mapMessageType(String type) {
		final String[] types = {"", "key", "gesture", "smiley", "image", "text"};
		for (int i = 1; i < types.length; i++) {
			if (types[i].equals(type)) {
				return i;
			}
		}
		return 0;
	}
	
	public static void receive(Context ctx, Uri uri) throws Exception {
		//String peer = uri.getQueryParameter("peer");
		int type = mapMessageType(uri.getQueryParameter("class"));
		String val = uri.getQueryParameter("val");
		String user = uri.getQueryParameter("user");
		
		boolean autospace = Boolean.parseBoolean(uri.getQueryParameter("autospace")) ;
		
		uri.getQueryParameter("autospace");
		
		if (writer != null && user.equals(writer.getPeer())) {
			writer.updateElement(type, val, user);
			if (autospace) {
				writer.updateElement(1, "sp", user);
			}
			return;
		}
		
		StringBuilder note = new StringBuilder();
		// type time length value
		note.append(type);
		note.append("\t");
		note.append(System.currentTimeMillis());
		note.append("\t");
		note.append(val.length());
		note.append("\t");
		note.append(val);
		note.append("\r\n");
		
		SDCard.saveMessage(user, note.toString());
		if (autospace) {
			SDCard.saveMessage(user, "1\t"+System.currentTimeMillis()+"\t2\tsp\r\n");
		}
		
		if (writer != null) {
			writer.updateNotification();
		} else {
			StatusHelper.addIncomingNotification(ctx, user);
		}
	}
	
	public static void processMessage(String peer, WriteActivity act) throws IOException {
		File file = SDCard.getMessage(peer);
		if (file == null) {
			return;
		}
		BufferedReader fr = new BufferedReader(new FileReader(file));
		String line = null;
		try {
			while ( (line = fr.readLine()) != null) {
				// type time length message
				String[] sa = line.split("\t", 4);
				int type = Integer.parseInt(sa[0]);
				String val = sa[3];
				
				act.addElement(type, val, peer);
			}
		} finally {
			fr.close();
		}
	}
	
	public static void saveSession(String peer, DocumentView doc) throws Exception {
		SDCard.saveSession(peer, doc);
	}
	
	public static void restoreSession(String peer, DocumentView doc) throws Exception {
		SDCard.restoreSession(peer, doc);
	}

	public static void sendImage(Context ctx, String peer, ImageElement el) throws Exception {
		Uri base = Uri.parse(BIN_SEBD);
		Builder b = base.buildUpon();
		b.appendQueryParameter("peer", peer);
		b.appendQueryParameter("cache", "false");
		b.appendQueryParameter("data", "false");
		
		b.appendQueryParameter("class", "image");
		b.appendQueryParameter("val", encode(el.toJSON().toString()));

		String path = b.toString();
		final Uri uri = ContentHelper.buildUri(path);

		String rs = ContentHelper.getContent(ctx, uri);
		checkStatus(ctx, rs);
	}

	public static void sendText(BaseActivity ctx, String peer,
			TextElement text) throws Exception {
		Uri base = Uri.parse(BIN_SEBD);
		Builder b = base.buildUpon();
		b.appendQueryParameter("peer", peer);
		b.appendQueryParameter("cache", "false");
		b.appendQueryParameter("data", "false");
		b.appendQueryParameter("class", "text");
		
		String etext = encode(text.getType()+","+text.getColor()+","+text.getSize()+","+text.getText());
		
		b.appendQueryParameter("val", etext);

		String path = b.toString();
		final Uri uri = ContentHelper.buildUri(path);

		String rs = ContentHelper.getContent(ctx, uri);
		checkStatus(ctx, rs);
	}
}
